#!/usr/bin/env python
import sys
import re
import pickle

g_dict = {}
g_generate = 0
g_idx_file = ""
g_depth = 1000 # Is this enough?
g_path = ""
g_flist = ""
g_root = ""

# print out a tree with specified root
g_indent = 0
g_call_path = set() # for detecting recursive call
g_accessed = set()  # for reducing duplicated result
last_stack =[]      # a stack keeping whether the cording depth on call path is last
BODY_ONLY = 1
def show_st(root, flag):
    global g_indent, g_accessed, BODY_ONLY
    dict_keys = g_dict.keys();
    struct_specifier_r = re.compile("[a-zA-Z_0-9 ]*\sstruct\s+([a-zA-Z0-9_]+)\s")
    if root in dict_keys:
        g_call_path.add(root)
        g_accessed.add(root)
        struct = g_dict[root]
        for line in struct:
            if (flag == BODY_ONLY):
                head_r = re.compile("^struct")
                tail_r = re.compile("^}")
                m = head_r.search(line)
                n = tail_r.search(line)
                if (m or n):
                    continue

            line = "\t" * (g_indent + 0) + line.rstrip()
            #line =  line.rstrip()
            m = struct_specifier_r.search(line)
            if (m):
                key = m.group(1)
                if key in g_accessed:
                    line += " (^)"
                    print line
                    continue
                if key in g_call_path:
                    line += " (r)"
                    print line
                    continue
                else:
                    print line
                g_indent += 1
                show_st(key, BODY_ONLY)
                g_indent -= 1
            else:
                print line

        g_call_path.remove(root)

def dump_dic():
    global g_dict
    for k in g_dict.keys():
        print k
        struct = g_dict[k]
        for line in struct:
            print line.rstrip()

def usage():
    print """usage: st <.st file> <struct name>

This program parses the st file generated by the modified gcc and print out
a strut tree

   <.st file> : .st file generated by the modified gcc
<struct name> : struct name of the root
"""

def gen_db(st_file):
    start = 0
    l = []

    struct_start_r = re.compile("^struct\s+([a-zA-Z_][a-zA-Z_0-9]*).*{$")
    struct_end = re.compile("^}")

    st_file_h = open(st_file, 'r')

    # extract out struct with content
    for line in st_file_h:
        m = struct_start_r.search(line)
        if (m):
            start = 1
            struct_name = m.group(1)
            #print struct_name

        if (start):
            #print line.rstrip()
            l.append(line.rstrip())

        if (struct_end.search(line)):
            start = 0
            g_dict[struct_name] = l
            l = []

    st_file_h.close()




def main():
    global g_generate, g_idx_file, g_depth, g_path, g_flist, g_root
    global g_dict

    if len(sys.argv) != 3:
        usage()
        sys.exit(1)

    st_file = sys.argv[1]
    root = sys.argv[2]

    gen_db(st_file)
    show_st(root, 0)

main()
